<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Tetris</title>
<style>
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,button,textarea,p,blockquote,th,td{
	padding:0;
	margin:0;
}
body{
	font-family: "Helvetica Neue", "Hiragino Sans GB", "Segoe UI", "Microsoft Yahei", "微软雅黑", Tahoma, Arial, STHeiti, sans-serif;
	font-size:12px;
	background:#fff;
	color:#333;
}
a{
	outline:none;
	-moz-outline:none;
	text-decoration:none;
}
.head{
	height:50px;
	line-height:50px;
	padding-left:20px;
	border-bottom:#eee;
	box-shadow: 1px 1px 5px #ccc;
}
.head h1{
	font-weight:normal;
	font-size:22px;
}
.head h1 span{
	float:right;
	font-size:12px;
	color:#999;
	line-height:14px;
	margin:30px 10px 0 0;
}
.wrap{
	width:1000px;
	margin:80px auto;
}
.play_wrap{
	padding-left:260px;
}
#play_area{
	float:left;
	width:300px;
	height:480px;
	margin:auto;
	background-color: #fefefe;
	border-radius:2px;
	color: black;
	box-shadow: 0px 0px 8px #e5e5e5;
	padding:1px 0 0 1px;
}
#play_area .play_cell{
	float:left;
	width:19px;
	height:19px;
	border:1px solid #eee;
	margin:-1px 0 0 -1px;
}
#play_area .play_cell.active{
	background:#999;
	border:1px solid #ccc;
}
#play_area .play_cell.goal{
	background: #0C0;
}
.play_menu{
	float:left;
	margin-left:60px;
	font-size:14px;
	padding-top:20px;
}
.play_menu #play_nextType{
	width:60px;
	height:60px;
	padding:1px 0 0 1px;
	margin:10px 0 20px 00px;
}
.play_menu .play_mini_cell{
	float:left;
	width:14px;
	height:14px;
	border:1px solid #fff;
	margin:-1px 0 0 -1px;
}
.play_menu .play_mini_cell.active{
	background:#999;
	border:1px solid #ccc;
}
.play_menu p{
	line-height:200%;
	clear:both;
}
.play_menu a.play_btn{
	display:block;
	margin-bottom:20px;
	width:80px;
	height:28px;
	line-height:28px;
	text-align:center;
	text-decoration:none;
	color:#333;
	background:#fefefe;
	border:1px solid #eee;
	border-radius: 2px;
	box-shadow: 1px 1px 2px #eee;
	border-color: #ddd #d2d2d2 #d2d2d2 #ddd;
	outline:none;
    -moz-outline:none;
}
.play_menu a.play_btn:hover{
	background-color: #fcfcfc;
	border-color: #ccc;
	box-shadow: inset 0 -2px 6px #eee;
}
.play_menu a#play_btn_level{
	position:relative;
	margin-bottom:30px;
}
.level_text{
	margin-left:-10px;
}
.level_icon{
	display:block;
	position:absolute;
	top:12px;
	right:16px;
	width:0;
	height:0;
	overflow:hidden;
	border:5px solid #FFF;
	border-color:#999 transparent transparent transparent;
}
.level_menu{
	position:absolute;
	margin:-30px 0 0px 1px;
	display:none;
}
.level_menu ul{
	list-style:none;
}
.level_menu li{
	float:left;
}
.level_menu li a{
	display:block;
	padding:3px 10px;
	border:1px solid #e8e8e8;
	margin-left:-1px;
	color:#09c;
}
.level_menu li a:hover{
	background:#09c;
	color:#fefefe;
}
</style>
<script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<script type="text/javascript">
var Tetris = function(options){
	this.e_playArea = $("#play_area");
	this.e_startBtn = $("#play_btn_start");
	this.e_playScore = $("#play_score");
	this.e_playDirection = $("#play_direction");
	this.e_levelBtn = $("#play_btn_level");
	this.e_levelMenu = $("#play_menu_level");
	this.e_nextType = $("#play_nextType");
	
	this.cellCol = 15;
	this.cellRow = 24;
	this.cellArr = [];
	this.miniCellArr = [];
	this.score = 0;
	this.direction = "bottom";
	this.timer = null;
	this.interval = [600,300,100];
	this.levelScore = [10,20,40];
	this.doubleScore = [1,4,10,20];
	this.level = 1;
	
	this.playing = false;
	this.turning = false;
	this.death = false;
	
	this.offsetCol = Math.floor(this.cellCol/2);
	this.offsetRow = -3;
	this.offsetFix = 0;
	this.tetrisArr = [];
	this.tetrisArr[0] = [[0,1,this.cellCol,this.cellCol+1],[0,1,this.cellCol,this.cellCol+1]];
	this.tetrisArr[1] = [[1,this.cellCol-1,this.cellCol,this.cellCol+1],[0,this.cellCol,this.cellCol*2,this.cellCol*2+1],
						 [this.cellCol-1,this.cellCol,this.cellCol+1,this.cellCol*2-1],[-1,0,this.cellCol,this.cellCol*2]
						];
	this.tetrisArr[2] = [[-1,this.cellCol-1,this.cellCol,this.cellCol+1],[0,1,this.cellCol,this.cellCol*2],
						 [this.cellCol-1,this.cellCol,this.cellCol+1,this.cellCol*2+1],[0,this.cellCol,this.cellCol*2-1,this.cellCol*2]
						];
	this.tetrisArr[3] = [[0,this.cellCol,this.cellCol+1,this.cellCol*2+1],[this.cellCol,this.cellCol+1,this.cellCol*2-1,this.cellCol*2]];
	this.tetrisArr[4] = [[0,this.cellCol-1,this.cellCol,this.cellCol*2-1],[this.cellCol-1,this.cellCol,this.cellCol*2,this.cellCol*2+1]];
	this.tetrisArr[5] = [[0,this.cellCol-1,this.cellCol,this.cellCol+1],[0,this.cellCol,this.cellCol+1,this.cellCol*2],
						 [this.cellCol-1,this.cellCol,this.cellCol+1,this.cellCol*2],[0,this.cellCol-1,this.cellCol,this.cellCol*2]
						];
	this.tetrisArr[6] = [[0,this.cellCol,this.cellCol*2,this.cellCol*3],[this.cellCol-1,this.cellCol,this.cellCol+1,this.cellCol+2]];
	this.tetrisType = [1,1];
	this.tetrisType = [1,0];
	this.tetrisTypeArr = [];
	
	this.preTetris = [];
	this.thisTetris = [];
	this.fullArr = [];
	
	this.start();
};
Tetris.prototype = {
	start:function(){
		this.init();
		this.menu();
		this.control();
	},
	setOptions:function(options){
		this.score = options.score === 0 ? options.score : (options.score|| this.score);
		this.level = options.level === 0 ? options.level : (options.level|| this.level);
	},
	resetArea:function(){
		$(".play_cell.active").removeClass("active");
		this.setOptions({
			"score": 0
		});
		this.e_playScore.html(this.score);
	},
	menu:function(){
		var self = this;
		
		this.e_startBtn.click(function(){
			self.e_levelMenu.hide();
			if(self.playing){
				self.pause();
			}else if(self.death){
				self.resetArea();
				self.play();
			}else{
				self.play();
			}
		});
		this.e_levelBtn.click(function(){
			if(self.playing) return;
			self.e_levelMenu.toggle();
		});
		this.e_levelMenu.find("a").click(function(){
			self.e_levelMenu.hide();
			self.e_levelBtn.find(".level_text").html($(this).html())
			self.setOptions({
				"level": $(this).attr("level")
			});
			//alert(self.interval[self.level])
		})
	},
	play:function(){
		var self = this;
		this.e_startBtn.html("暂停");
		this.playing = true;
		this.death = false;
		if(this.turning){
			this.timer = setInterval(function(){
				self.offsetRow++;
				self.showTetris();
			},this.interval[this.level]);
		}else{
			this.nextTetris();
		}
		
	},
	pause:function(){
		this.e_startBtn.html("开始")
		this.playing = false;
		clearTimeout(this.timer);
	},
	init:function(){
		var self = this, _ele, _miniEle, _arr = [];
		for(var i = 0; i < this.cellRow; i++){
			for(var j = 0; j < this.cellCol; j++){
				_ele = document.createElement("div");
				_ele.className = "play_cell";
				_ele.id = "play_cell_" + i + "_" + j;
				this.cellArr.push($(_ele));
				this.e_playArea.append(_ele);
			}
		}
		
		for(var m = 0; m<16; m++){
			_miniEle = document.createElement("div");
			_miniEle.className = "play_mini_cell";
			this.miniCellArr.push($(_miniEle));
			this.e_nextType.append(_miniEle);
		}
		
		for(var k = 0, klen = this.tetrisArr.length; k<klen; k++){
			for(var j = 0, jlen = this.tetrisArr[k].length; j<jlen; j++){
				this.tetrisTypeArr.push([k,j]);
			}
		};
		
		this.nextType = this.tetrisTypeArr[Math.floor(this.tetrisTypeArr.length * Math.random())];
		this.showNextType();
		
	},
	control:function(){
		var self = this;
		$("html").keydown(function(e){
			if(!self.playing) return !self.playing;
			switch (e.keyCode) {
				case 37:
					self.direction = "left";
					break;
				case 38:
					self.direction = "top";
					break;
				case 39:
					self.direction = "right";
					break;
				case 40:
					self.direction = "bottom";
					break;
				default:
					return;
					break;
			}
			self.e_playDirection.html(self.direction);
			self.drive();
			return false;
		})
	},
	changTetris:function(){
		var _len = this.tetrisArr[this.tetrisType[0]].length;
		if(this.tetrisType[1] < _len-1){
			this.tetrisType[1]++;
		}else{
			this.tetrisType[1] = 0;
		}
	},
	drive:function(){
		switch (this.direction) {
			case "left":
				if(this.offsetCol > 0) this.offsetCol --;
				break;
			case "top":
				this.changTetris();
				break;
			case "right":
				this.offsetCol ++;
				break;
			case "bottom":
				if(this.offsetRow < this.cellRow-2) this.offsetRow ++;
				break;
			default:break;
		}
		this.showTetris(this.direction);
	},
	showTetris:function(dir){
		var _tt = this.tetrisArr[this.tetrisType[0]][this.tetrisType[1]],
		_ele,self=this;
		this.turning = true;
		this.thisTetris = [];
		for(var i=_tt.length-1; i>=0; i--){
			_ele = this.cellArr[_tt[i] + this.offsetCol + this.offsetRow * this.cellCol];
			if(this.offsetCol<7 && (_tt[i] + this.offsetCol + 1)%this.cellCol == 0){
				this.offsetCol ++;
				return;
			}else if(this.offsetCol>7 && (_tt[i] + this.offsetCol)%this.cellCol == 0){
				this.offsetCol --;
				return;
			}
			if(_ele && _ele.hasClass("active") && dir == "left" && ($.inArray(_ele,this.preTetris)<0)){
				if(($.inArray(_ele, this.cellArr) - $.inArray(this.preTetris[i], this.cellArr)) % this.cellCol !=0){
					this.offsetCol ++;
					return;
				}
			}
			if(_ele && _ele.hasClass("active") && dir == "right" && ($.inArray(_ele,this.preTetris)<0)){
				if(($.inArray(_ele, this.cellArr) - $.inArray(this.preTetris[i], this.cellArr)) % this.cellCol !=0){
					this.offsetCol --;
					return;
				}
			}
			if(_ele){
				if(_ele.hasClass("active") && ($.inArray(_ele,this.preTetris)<0)){
					this.tetrisDown();
					return;
				}else{
					this.thisTetris.push(_ele);
				}
			}else if(this.offsetRow > 0 ){
				this.tetrisDown();
				return;
			}
		};
		for(var j=0, jlen = this.preTetris.length; j<jlen; j++){
			this.preTetris[j].removeClass("active");
		}
		for(var k=0, klen = this.thisTetris.length; k<klen; k++){
			this.thisTetris[k].addClass("active");
		}
		this.preTetris = this.thisTetris.slice(0);
	},
	tetrisDown:function(){
		clearInterval(this.timer);
		var _index;
		this.turning = false;
		forOuter:
		for(var j = 0, jlen = this.preTetris.length; j<jlen; j++){
			_index = $.inArray(this.preTetris[j],this.cellArr);
			for(var k = _index - _index%this.cellCol, klen = _index - _index%this.cellCol + this.cellCol; k<klen; k++){
				if(!this.cellArr[k].hasClass("active")){
					continue forOuter;
				}
			}
			if($.inArray(_index - _index%this.cellCol,this.fullArr)<0) this.fullArr.push(_index - _index%this.cellCol);
		}
		if(this.fullArr.length){
			this.getScore();
			return;
		}
		for(var i = 6; i<9; i++){
			if(this.cellArr[i].hasClass("active")){
				this.gameOver();
				return;
			}
		}
		this.nextTetris();
	},
	nextTetris:function(){
		var self = this;
		clearInterval(this.timer);
		this.preTetris = [];
		this.offsetRow = -2;
		this.offsetCol = 7;
		this.tetrisType = this.nextType;
		this.nextType = this.tetrisTypeArr[Math.floor(this.tetrisTypeArr.length * Math.random())];
		this.showNextType();
		this.timer = setInterval(function(){
			self.offsetRow++;
			self.showTetris();
		},this.interval[this.level]);
	},
	showNextType:function(){
		var _nt = this.tetrisArr[this.nextType[0]][this.nextType[1]],_ele,_index;
		this.e_nextType.find(".active").removeClass("active");
		for(var i = 0, ilen = _nt.length; i<ilen; i++){
			if(_nt[i] > this.cellCol-2){
				_index = (_nt[i]+2)%this.cellCol-2 + 1 + 4*parseInt((_nt[i]+2)/this.cellCol);
			}else{
				_index = _nt[i] + 1;
			}
			_ele = this.miniCellArr[_index];
			_ele.addClass("active");
		}
	},
	getScore:function(){
		var self = this;
		for(var i = this.fullArr.length-1; i>=0; i--){
			for(var j = 0; j<this.cellCol; j++){
				this.cellArr[j+this.fullArr[i]].removeClass("active");
					if(j == this.cellCol-1){
						for(var k = this.fullArr[i]; k>=0; k--){
						if(this.cellArr[k].hasClass("active")){
							this.cellArr[k].removeClass("active");
							this.cellArr[k + this.cellCol].addClass("active");
						}
					}
				}
			}
			
		}
		this.score += this.levelScore[this.level]*this.doubleScore[this.fullArr.length-1];
		this.e_playScore.html(this.score); 
		this.fullArr = [];
		this.nextTetris();
	},
	gameOver:function(){
		this.death = true;
		this.pause();
		return;
	}
}
$(document).ready(function(e) {
	var t = new Tetris();
});
</script>
</head>
<body>
<div class="head">
<h1><span>网页版俄罗斯方块游戏</span></h1>
</div>
<div class="wrap">
<div class="play_wrap">	
<div id="play_area"></div>
        <div class="play_menu">
        	<p>下一个：</p>
            <div id="play_nextType">	
            </div>
        	<a id="play_btn_start" class="play_btn" href="javascript:void(0);" unselectable="on">开始</a>
            <a id="play_btn_level" class="play_btn" href="javascript:void(0);" unselectable="on">
            	<span class="level_text">中等</span>
            	<span class="level_icon"></span>
            </a>
            	<div class="level_menu" id="play_menu_level">
                	<ul>
                    	<li>
                        	<a href="javascript:void(0);" level=0 >简单</a>
                        </li>
                        <li>
                        	<a href="javascript:void(0);" level=1 >中等</a>
                        </li>
                        <li>
                        	<a href="javascript:void(0);" level=2 >困难</a>
                        </li>
                    </ul>
                </div>
        	<p>分数：<span id="play_score">0</span></p>
        	<p>方向：<span id="play_direction">bottom</span></p>
            <p>说明：<br>
            -“下”、“左”、“右”键控制方向，“上”为变形；<br>
            -游戏开始前、暂停时可调整难度；<br>
            -难度分“简单”、“中等”、“困难”三级；<br>
            -对应的分值为10、20、40；<br>
            -多行同时消去的倍数为1、4、10、20；
      </p>
        </div>
    </div>
</div>
</body>
</html>